Document layout equivalences for pointer types#2291
Conversation
The pointer-to-pointer cast rules and the wide-pointer validity rule both speak of the *metadata* of a pointer, but we hadn't explicitly defined the term (even though we had defined the contents of that metadata). Let's do that and link to it.
We refer to the unsized tail of a type, but we hadn't defined it. Let's do that and link to the definition.
The validity rule for the metadata of a wide reference, `Box<T>`, or raw pointer mentions `dyn Trait` and slice but had omitted `str`. Let's fix that.
We document that, for references and `Box<T>`, pointed-to values with slice or `str` metadata must be no larger than `isize::MAX`. We hadn't required this for pointed-to values with `dyn` metadata. It's tempting to think this isn't necessary since we separately require that the metadata point to a vtable generated by the compiler, which ensures the encoded size of the erased type is OK. But the bound is on the total size of the pointed-to value, including any sized prefix of a type with an unsized tail. Since the prefix combined with the size in the vtable can push us past the limit, we need the separate restriction. Let's apply the rule to both cases and add an admonition to remind ourselves of why this is needed.
We say that pointers to DSTs store metadata and what that metadata is for pointers to slices, `str`, and trait objects. But a struct or tuple with an unsized tail is itself a DST, and we hadn't said what the metadata is for pointers to these unsized types. Now that we've defined *metadata* and *unsized tail*, let's complete this enumeration.
We guarantee various things about the layout of pointers and references, but we'd made no guarantees of equivalence between two pointers to distinct unsized types that differ in the unsized tail. Let's make some useful guarantees about this.
This comment has been minimized.
This comment has been minimized.
|
|
||
| - `T` and `U` are both sized types. | ||
| - `T` and `U` both have a [slice] or [`str`] as their [unsized tail]. | ||
| - `T` and `U` both have a [trait object] as their unsized tail. |
There was a problem hiding this comment.
Doesn't this also require that the VTable is the same between both traits? Otherwise you would end up having exactly this problem? Or does this just refer to the fact that the internal layout of the vtable is so that you could convert between both, but you get the "wrong" behaviour in this cases?
There was a problem hiding this comment.
This is only a guarantee about the layout of wide pointers. It doesn't guarantee that you can transmute, and we exclude trait object unsized tails in #2292.
There was a problem hiding this comment.
It doesn't guarantee that you can transmute,
That might be worth making explicit, since people often take "same layout" as meaning "I may transmute".
|
Given that the PR this is stacked on landed, it'd be great if you could rebase this PR to make the diff view reflect just what is new. |
| > Though you should not rely on this, all pointers to <abbr title="Dynamically Sized Types">DSTs</abbr> are currently twice the size of the size of `usize` and have the same alignment. | ||
|
|
||
| r[layout.pointer.parametric] | ||
| The raw pointer types `*const T` and `*const U` have the same layout, as do `*mut T` and `*mut U`, the shared references `&T` and `&U`, and the mutable references `&mut T` and `&mut U`, in each of the following cases: |
There was a problem hiding this comment.
"Same layout" here seems to mean "same size and alignment", based on the assertions below? That's not really useful on its own though. And it's really hard to define "same layout" in general for two arbitrary types.
So, I am honestly not sure what this is supposed to guarantee. It is much easier to precisely say "you may transmute from A to B under precondition P, and then X will happen with the value".
Unless you really just mean "same size and alignment", in which case I think we should say that explicitly rather than saying using undefined terms such as "same layout".
We guarantee various things about the layout of pointers and references, but we'd made no guarantees of equivalence between two pointers to distinct unsized types that differ in the unsized tail. Let's make some useful guarantees about this.
I'm breaking this out from #2282 so that these may be considered in smaller pieces. This is stacked on #2289 (and on the ones it's stacked on).
cc @ehuss @RalfJung @Mark-Simulacrum